﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DiscreteEventModel {

    public partial class DiscreteState<TContext> {

        public abstract class Transition<TTargetState> : DiscreteEvent<TContext>
            where TTargetState : DiscreteState<TContext> {

            public abstract IEnumerable<TTargetState> Targets { get; }
            protected abstract void OnCommit(TTargetState target);
            
            protected override DiscreteTime Commit(IRuntime runtime) {
                foreach(TTargetState target in this.Targets) {
                    target.Synchronize(runtime);
                    this.OnCommit(target);
                    runtime.ScheduleEvent(target, DiscreteTime.Null);
                }
                return this.Resolve(runtime.Context);
            }

            protected Transition(IRuntime runtime, double timing){
                runtime.ScheduleEvent(this, runtime.Time + timing);
            }
        }

        public abstract class Transition<TTargetState, TSourceState> : Transition<TTargetState>
            where TSourceState : DiscreteState<TContext>
            where TTargetState : DiscreteState<TContext> {

            public readonly TSourceState Source;

            protected override DiscreteTime Commit(IRuntime runtime) {
                this.Source.Synchronize(runtime);
                return base.Commit(runtime);
            }

            protected Transition(IRuntime runtime, double timing, TSourceState source)
                : base(runtime, timing) {
                this.Source = source;
            }
        }
    }
}
